package com.xyzwps.orm.ebean.repository;

import com.xyzwps.orm.exception.TagDuplicateException;
import com.xyzwps.orm.model.Tag;
import com.xyzwps.orm.repository.TagRepository;
import com.xyzwps.orm.util.ExceptionUtils;
import io.ebean.Database;

import javax.persistence.EntityNotFoundException;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

public class EbeanTagRepository implements TagRepository {

    private final Database db;

    public EbeanTagRepository(Database db) {
        this.db = Objects.requireNonNull(db);
    }

    @Override
    public int insert(Tag tag) {
        try {
            var tagEntity = TagEntity.fromTag(tag);
            db.insert(tagEntity);
            return tagEntity.getTagId();
        } catch (Exception ex) {
            if (ExceptionUtils.causedBy(ex, SQLIntegrityConstraintViolationException.class)) {
                throw new TagDuplicateException(tag.getTagName());
            } else {
                throw new IllegalStateException(ex);
            }
        }
    }

    @Override
    public void update(Tag tag) {
        try {
            db.update(TagEntity.fromTag(tag));
        } catch (Exception ex) {
            if (ExceptionUtils.causedBy(ex, SQLIntegrityConstraintViolationException.class)) {
                throw new TagDuplicateException(tag.getTagName());
            } else if (ExceptionUtils.causedBy(ex, EntityNotFoundException.class)) {
                //noinspection UnnecessaryReturnStatement
                return;
            } else {
                throw new IllegalStateException(ex);
            }
        }
    }

    @Override
    public void delete(int tagId) {
        db.delete(TagEntity.class, tagId);
    }

    @Override
    public Optional<Tag> selectByTagId(int tagId) {
        var te = db.find(TagEntity.class, tagId);
        if (te == null) return Optional.empty();
        return Optional.of(te.toTag());
    }

    @Override
    public List<Tag> selectAllForUser(int userId) {
        return db.findDto(Tag.class, "select tag_id, tag_name, user_id from tag where user_id = ?")
                .setParameter(1, userId)
                .findList();
    }
}
